package com.haoshuang.zhouzhoubang.widget

import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintSet
import com.blankj.utilcode.util.SizeUtils
import com.haoshuang.zhouzhoubang.R
import com.haoshuang.zhouzhoubang.databinding.CustomUploadViewBinding
import com.haoshuang.zhouzhoubang.ui.adapter.UploadViewAdapter
import com.haoshuang.zhouzhoubang.ui.dialog.ChooseMediaTypeDialog
import com.haoshuang.zhouzhoubang.utils.ChooseMediaUtils
import com.haoshuang.zhouzhoubang.utils.OSSUploadUtils
import com.luck.lib.camerax.CustomCameraConfig
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.ImageViewerPopupView
import com.lxj.xpopup.interfaces.OnSrcViewUpdateListener
import com.lxj.xpopup.util.SmartGlideImageLoader
import com.mufeng.libs.utils.toast
import com.mufeng.libs.utils.view.click
import com.mufeng.libs.utils.view.clickWithTrigger
import com.mufeng.libs.utils.view.gone
import com.mufeng.libs.utils.view.load
import com.mufeng.libs.utils.view.removeAllAnimation
import com.mufeng.libs.utils.view.vertical
import com.mufeng.libs.utils.view.visible
import com.mufeng.libs.utils.view.visibleOrGone
import com.noober.background.drawable.DrawableCreator

/**
 * 自定义上传控件
 * 支持图片和视频上传
 * 数量: 图片最大9张
 * 视频最多一张
 */
class CustomUploadView : FrameLayout {

    /**
     * 是不是单张, 默认多张
     */
    private var isSingle = false

    /**
     * 图片最大数量
     */
    private var maxImageCount = 9

    /**
     * 视频最大数量
     */
    private var maxVideoCount = 1

    /**
     * 每行个数
     */
    private var rowCount = 4

    /**
     * 上传类型 1: 图片, 2: 视频, 3: 图片和视频, 默认图片
     */
    private var mediaType = 1

    /**
     * 图片圆角 仅适用于单张图片
     */
    private var isCircular = false

    /**
     * 图片圆角 仅适用于单张图片
     */
    private var imageRadius = 0f

    /**
     * 是否需要上传 默认需要上传
     */
    private var isNeedUpload = true

    /**
     * 是否直接打开相机
     */
    private var openCamera = false

    /**
     * 默认上传图片
     */
    private var defaultSrc = R.drawable.ic_add_image

    /**
     * 图片缩放类型
     */
    private var scaleType: Int = 0

    /**
     * 单图的宽高比
     */
    private var dimensionRatio = "1:1"

    /**
     * 是否可以编辑  默认可以编辑
     */
    private var isEdit = true

    private var binding: CustomUploadViewBinding

    /**
     * 单个上传的实体
     */
    private var singleMedia: UploadFileBean? = null

    private val data = mutableListOf<UploadFileBean>()
    private lateinit var adapter: UploadViewAdapter

    constructor(context: Context) : this(context, null, 0)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context, attrs, defStyleAttr
    ) {

        // 获取可配置的属性  设置给控件
        val attr = context.obtainStyledAttributes(attrs, R.styleable.CustomUploadView)
        isSingle = attr.getBoolean(R.styleable.CustomUploadView_isSingle, false)
        maxImageCount = attr.getInt(R.styleable.CustomUploadView_imageMaxSize, 9)
        maxVideoCount = attr.getInt(R.styleable.CustomUploadView_videoMaxSize, 1)
        rowCount = attr.getInt(R.styleable.CustomUploadView_rowCount, 4)
        mediaType = attr.getInt(R.styleable.CustomUploadView_mediaType, 1)
        isCircular = attr.getBoolean(R.styleable.CustomUploadView_isCircular, false)
        imageRadius = attr.getDimension(R.styleable.CustomUploadView_radius, 0f)
        isNeedUpload = attr.getBoolean(R.styleable.CustomUploadView_canUpload, true)
        openCamera = attr.getBoolean(R.styleable.CustomUploadView_openCamera, false)
        defaultSrc = attr.getResourceId(R.styleable.CustomUploadView_defaultSrc, R.drawable.ic_add_image)
        scaleType = attr.getInt(R.styleable.CustomUploadView_cuv_scaleType, 0)
        dimensionRatio = attr.getString(R.styleable.CustomUploadView_cuv_dimensionRatio)?:"1:1"
        isEdit = attr.getBoolean(R.styleable.CustomUploadView_isEdit, true)
        attr.recycle()
        val root = inflate(context, R.layout.custom_upload_view, this)
        binding = CustomUploadViewBinding.bind(root)
        initView()
    }

    private fun initView() {

        binding.apply {
            if (isSingle) {
                rivImage.load(defaultSrc)
                if(scaleType != 0) {
                    rivImage.scaleType = when (scaleType) {
                        1 -> ImageView.ScaleType.FIT_XY
                        2 -> ImageView.ScaleType.FIT_START
                        3 -> ImageView.ScaleType.FIT_CENTER
                        4 -> ImageView.ScaleType.FIT_END
                        5 -> ImageView.ScaleType.CENTER
                        6 -> ImageView.ScaleType.CENTER_CROP
                        7 -> ImageView.ScaleType.CENTER_INSIDE
                        else -> null
                    }
                }
                //layout_constraintDimensionRatio 设置图片宽高比
                val constraintSet = ConstraintSet()
                constraintSet.clone(clSingleMedia)
                constraintSet.setDimensionRatio(rivImage.id, "H,${dimensionRatio}")
                constraintSet.applyTo(clSingleMedia)

                // 单图/单视频 选择上传
                uploadSingleMedia()
            } else {
                uploadMultiMedia()
            }
        }


    }

    /**
     * 设置是否可以编辑
     */
    fun setCanEdit(isEdit: Boolean) {
        this.isEdit = isEdit
        adapter.setCanEdit(isEdit)
        adapter.notifyDataSetChanged()
    }

    private fun CustomUploadViewBinding.uploadMultiMedia() {
        adapter = UploadViewAdapter(context, data, defaultSrc)
        recyclerView.visible()
        clSingleMedia.gone()
        recyclerView.vertical(rowCount).adapter = adapter
        adapter.setCanEdit(isEdit)
        val max = when(mediaType){
            1 -> maxImageCount
            2 -> maxVideoCount
            else -> maxImageCount + maxVideoCount
        }
        adapter.setSelectMax(max)
        adapter.setOnItemClickListener(object : UploadViewAdapter.OnItemClickListener {
            override fun onItemClick(v: View, position: Int) {
                if (!isEdit) {
                    XPopup.Builder(context)
                        .asImageViewer(
                            v.findViewById(R.id.ivImage),
                            position,
                            adapter.getData().map { it.url } as List<Any>,
                            object : OnSrcViewUpdateListener {
                                override fun onSrcViewUpdate(
                                    popupView: ImageViewerPopupView,
                                    position: Int
                                ) {
                                    popupView.updateSrcView(
                                        recyclerView.getChildAt(position).findViewById(R.id.ivImage)
                                    )
                                }
                            },
                            SmartGlideImageLoader(),
                        )
                        .show()
                    return
                }
                // 重试
                val bean = adapter.getData()[position]
                if (bean.status == 3){
                    // 重试
                    OSSUploadUtils.uploadFile(
                        "app/upload",
                        bean.localMedia?.realPath ?: ""
                    ) {
                        start {}
                        error { clientException, serviceException ->
                            bean.status = 3
                            adapter.notifyItemChanged(position)
                        }
                        success {
                            bean.url = it
                            bean.status = 2
                            adapter.notifyItemChanged(position)
                            if (onUploadResultListener != null) {
                                onUploadResultListener?.onUploadResult(arrayListOf(bean))
                            }
                        }
                        progress { currentSize, totalSize ->
                            bean.progress = (currentSize * 100 / totalSize).toInt()
                            adapter.notifyItemChanged(position)
                        }
                    }
                }
            }

            override fun openPicture() {
                val imageMax = if (mediaType == 2) 0 else maxImageCount - adapter.getData().filter { !it.isVideo }.size
                val videoMax = if (mediaType == 1) 0 else maxVideoCount - adapter.getData().filter { it.isVideo }.size
                if (openCamera){
                    when(mediaType){
                        1 -> {
                            // 点击去拍照
                            if (imageMax == 0) {
                                toast("最多可上传${maxImageCount}张图片")
                                return
                            }
                            uploadMultiMediaWithCamera(SelectMimeType.ofImage(),0,imageMax)
                        }
                        2 -> {
                            // 点击去录像
                            if (videoMax == 0) {
                                toast("最多可上传${maxVideoCount}个视频")
                                return
                            }
                            uploadMultiMediaWithCamera(SelectMimeType.ofVideo(),videoMax, 0)
                        }
                        else -> {
                            // 显示弹窗判断
                            XPopup.Builder(context)
                                .asCustom(ChooseMediaTypeDialog(context){
                                    when(it){
                                        0 -> {
                                            // 点击去拍照
                                            if (imageMax == 0) {
                                                toast("最多可上传${maxImageCount}张图片")
                                                return@ChooseMediaTypeDialog
                                            }
                                            uploadMultiMediaWithCamera(SelectMimeType.ofImage(),0, imageMax)
                                        }
                                        1 -> {
                                            // 点击去录像
                                            if (videoMax == 0) {
                                                toast("最多可上传${maxVideoCount}个视频")
                                                return@ChooseMediaTypeDialog
                                            }
                                            uploadMultiMediaWithCamera(SelectMimeType.ofVideo(),videoMax, 0)
                                        }
                                    }
                                }).show()
                        }
                    }
                }else {
                    // 点击去上传
                    ChooseMediaUtils(context).selectMedia(
                        when (mediaType) {
                            1 -> {
                                SelectMimeType.ofImage()
                            }

                            2 -> {
                                SelectMimeType.ofVideo()
                            }

                            else -> {
                                SelectMimeType.ofAll()
                            }
                        },
                        true,
                        true,
                        imageMax, videoMax,
                        null,
                        object :
                            OnResultCallbackListener<LocalMedia> {
                            override fun onResult(result: ArrayList<LocalMedia>?) {
                                if (result?.isEmpty() == true) return
                                val list = result?.map {
                                    UploadFileBean(
                                        it,
                                        "",
                                        0,
                                        PictureMimeType.isHasVideo(it.mimeType),
                                        1
                                    )
                                } ?: mutableListOf()

                                adapter.getData().addAll(list)
                                adapter.notifyDataSetChanged()
                                adapter.getData().forEachIndexed { index, bean ->
                                    if (bean.status == 1) {
                                        OSSUploadUtils.uploadFile(
                                            "app/upload",
                                            bean.localMedia?.realPath ?: ""
                                        ) {
                                            start {}
                                            error { clientException, serviceException ->
                                                bean.status = 3
                                                adapter.notifyItemChanged(index)
                                            }
                                            success {
                                                bean.url = it
                                                bean.status = 2
                                                adapter.notifyItemChanged(index)
                                                if (onUploadResultListener != null) {
                                                    onUploadResultListener?.onUploadResult(arrayListOf(bean))
                                                }
                                            }
                                            progress { currentSize, totalSize ->
                                                bean.progress =
                                                    (currentSize * 100 / totalSize).toInt()
                                                adapter.notifyItemChanged(index)
                                            }
                                        }
                                    }
                                }
                            }

                            override fun onCancel() {

                            }
                        }
                    )
                }
            }
        })
    }

    private fun CustomUploadViewBinding.uploadMultiMediaWithCamera(
        selectMimeType: Int,
        videoMax: Int,
        imageMax: Int,
    ){
        ChooseMediaUtils(context).openCamera(
            selectMimeType,
            videoMax,
            imageMax,
            object :
                OnResultCallbackListener<LocalMedia> {
                override fun onResult(result: ArrayList<LocalMedia>?) {
                    if (result?.isEmpty() == true) return
                    val list = result?.map {
                        UploadFileBean(
                            it,
                            "",
                            0,
                            PictureMimeType.isHasVideo(it.mimeType),
                            1
                        )
                    } ?: mutableListOf()

                    adapter.getData().addAll(list)
                    adapter.notifyDataSetChanged()
                    adapter.getData().forEachIndexed { index, bean ->
                        if (bean.status == 1) {
                            OSSUploadUtils.uploadFile(
                                "app/upload",
                                bean.localMedia?.realPath ?: ""
                            ) {
                                start {}
                                error { clientException, serviceException ->
                                    bean.status = 3
                                    adapter.notifyItemChanged(index)
                                }
                                success {
                                    bean.url = it
                                    bean.status = 2
                                    adapter.notifyItemChanged(index)
                                    if (onUploadResultListener != null) {
                                        onUploadResultListener?.onUploadResult(arrayListOf(bean))
                                    }
                                }
                                progress { currentSize, totalSize ->
                                    bean.progress =
                                        (currentSize * 100 / totalSize).toInt()
                                    adapter.notifyItemChanged(index)
                                }
                            }
                        }
                    }
                }

                override fun onCancel() {

                }
            }
        )
    }

    private fun CustomUploadViewBinding.uploadSingleMedia() {
        recyclerView.gone()
        clSingleMedia.visible()

        // 是不是圆形头像
        rivImage.isOval = isCircular
        // 设置圆角
        rivImage.cornerRadius = imageRadius
        val drawable = DrawableCreator.Builder()
            .setSolidColor(Color.parseColor("#4d000000"))
            .setCornersRadius(imageRadius)
            .setShape(if (isCircular)DrawableCreator.Shape.Oval else DrawableCreator.Shape.Rectangle)
            .build()
        llUpload.background = drawable

        clSingleMedia.clickWithTrigger {
            if (!isEdit) {
                if (singleMedia != null) {
                    XPopup.Builder(context)
                        .asImageViewer(rivImage, singleMedia?.url, SmartGlideImageLoader())
                        .show()
                }
                return@clickWithTrigger
            }
            if (singleMedia?.localMedia != null && singleMedia?.status == 3) {
                // 上传失败, 重新上传
                ivVideo.visibleOrGone(singleMedia?.isVideo == true)
                llUpload.visible()
                ivRetry.gone()
                tvUploadProgress.visible()
                tvUploadProgress.text = "0%"
                tvUploadStatus.text = "正在上传"
                OSSUploadUtils.uploadFile(
                    "app/upload",
                    singleMedia?.localMedia?.realPath ?: ""
                ) {
                    start { }
                    progress { currentSize, totalSize ->
                        val progress = (currentSize * 100 / totalSize).toInt()
                        singleMedia?.progress = progress
                        tvUploadProgress.text = "${progress}%"
                    }
                    error { clientException, serviceException ->
                        ivRetry.visible()
                        tvUploadProgress.gone()
                        tvUploadStatus.text = "点击重试"
                    }
                    success {
                        Log.e("TAG", "success: $it")
                        llUpload.gone()
                        singleMedia?.url = it
                        singleMedia?.status = 2
                        if (onUploadResultListener != null) {
                            onUploadResultListener?.onUploadResult(arrayListOf(singleMedia!!))
                        }
                    }
                }
            } else {
                // 点击选择图片/视频
                if (openCamera){
                    ChooseMediaUtils(context).openCamera(
                        when (mediaType) {
                            1 -> {
                                SelectMimeType.ofImage()
                            }

                            2 -> {
                                SelectMimeType.ofVideo()
                            }

                            else -> {
                                SelectMimeType.ofAll()
                            }
                        },
                        1,
                        1,
                        object :
                            OnResultCallbackListener<LocalMedia> {
                            override fun onResult(result: ArrayList<LocalMedia>?) {
                                if (result?.isEmpty() == true) return
                                singleMedia = UploadFileBean(
                                    result?.get(0),
                                    "",
                                    0,
                                    PictureMimeType.isHasVideo(result?.get(0)?.mimeType),
                                    1
                                )
                                rivImage.load(singleMedia?.localMedia?.realPath)
                                llUpload.visible()
                                ivVideo.visibleOrGone(PictureMimeType.isHasVideo(result?.get(0)?.mimeType))
                                ivRetry.gone()
                                tvUploadProgress.visible()
                                tvUploadProgress.text = "0%"
                                tvUploadStatus.text = "正在上传"
                                OSSUploadUtils.uploadFile(
                                    "app/upload",
                                    singleMedia?.localMedia?.realPath ?: ""
                                ) {
                                    start { }
                                    progress { currentSize, totalSize ->
                                        val progress = (currentSize * 100 / totalSize).toInt()
                                        singleMedia?.progress = progress
                                        tvUploadProgress.text = "${progress}%"
                                    }
                                    error { clientException, serviceException ->
                                        ivRetry.visible()
                                        tvUploadProgress.gone()
                                        tvUploadStatus.text = "点击重试"
                                    }
                                    success {
                                        Log.e("TAG", "success: $it")
                                        llUpload.gone()
                                        singleMedia?.url = it
                                        singleMedia?.status = 2
                                        if (onUploadResultListener != null) {
                                            onUploadResultListener?.onUploadResult(arrayListOf(singleMedia!!))
                                        }
                                    }
                                }
                            }

                            override fun onCancel() {

                            }
                        }
                    )
                }else {
                    ChooseMediaUtils(context).selectMedia(
                        when (mediaType) {
                            1 -> {
                                SelectMimeType.ofImage()
                            }

                            2 -> {
                                SelectMimeType.ofVideo()
                            }

                            else -> {
                                SelectMimeType.ofAll()
                            }
                        },
                        false,
                        true,
                        1, 1,
                        null,
                        object :
                            OnResultCallbackListener<LocalMedia> {
                            override fun onResult(result: ArrayList<LocalMedia>?) {
                                if (result?.isEmpty() == true) return
                                singleMedia = UploadFileBean(
                                    result?.get(0),
                                    "",
                                    0,
                                    PictureMimeType.isHasVideo(result?.get(0)?.mimeType),
                                    1
                                )
                                rivImage.load(singleMedia?.localMedia?.realPath)
                                llUpload.visible()
                                ivVideo.visibleOrGone(PictureMimeType.isHasVideo(result?.get(0)?.mimeType))
                                ivRetry.gone()
                                tvUploadProgress.visible()
                                tvUploadProgress.text = "0%"
                                tvUploadStatus.text = "正在上传"
                                OSSUploadUtils.uploadFile(
                                    "app/upload",
                                    singleMedia?.localMedia?.realPath ?: ""
                                ) {
                                    start { }
                                    progress { currentSize, totalSize ->
                                        val progress = (currentSize * 100 / totalSize).toInt()
                                        singleMedia?.progress = progress
                                        tvUploadProgress.text = "${progress}%"
                                    }
                                    error { clientException, serviceException ->
                                        ivRetry.visible()
                                        tvUploadProgress.gone()
                                        tvUploadStatus.text = "点击重试"
                                    }
                                    success {
                                        Log.e("TAG", "success: $it")
                                        llUpload.gone()
                                        singleMedia?.url = it
                                        singleMedia?.status = 2
                                        if (onUploadResultListener != null) {
                                            onUploadResultListener?.onUploadResult(arrayListOf(singleMedia!!))
                                        }
                                    }
                                }
                            }

                            override fun onCancel() {

                            }
                        }
                    )
                }
            }
        }
    }

    fun getSingleMedia(): UploadFileBean?{
        return singleMedia
    }

    fun getMediaList(): List<UploadFileBean>{
        return adapter.getData()
    }

    /**
     * 设置单张图片
     */
    fun setSingleMedia(url: String?){
        singleMedia = UploadFileBean(null, url, 0, false, 2)
        binding.rivImage.load(url, placeholder = defaultSrc, error = defaultSrc)
    }

    fun setMediaList(urls: List<UploadFileBean>){
        adapter.getData().clear()
        adapter.getData().addAll(urls)
        adapter.notifyDataSetChanged()
    }

    private var onUploadResultListener: OnUploadResultListener? = null

    fun setOnUploadResultListener(onUploadResultListener: OnUploadResultListener){
        this.onUploadResultListener = onUploadResultListener
    }

    interface OnUploadResultListener{
        fun onUploadResult(mediaList: List<UploadFileBean>)
    }
}

/**
 * 上传实体模型
 */
data class UploadFileBean(
    var localMedia: LocalMedia? = null,
    var url: String?,
    var progress: Int = 0, // 上传进度
    var isVideo: Boolean = false,
    var status: Int = 0, // 0: 未上传, 1: 上传中, 2: 上传成功, 3: 上传失败
)